////////////////////////////////////////////////////////////////////////////////
/*!	\file		testC45.hpp
**	\brief		Declares all the functionality for testing a C45Tree.
**	\author		Nate Cleveland
**	\date		2/7/2003 1:53:22 PM
**	\par		DESCRIPTION:
					- simple object that fulfills all requirements stated in 
					C45.hpp and C45Generator.hpp.
**					
**	\par		REMARKS:
**					
*/
////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "../dTrees/dTreeCommons.hpp"

namespace DTree
{

	////////////////////////////////////////////////////////////////////////////////
	/*!	\class		TestExpander
	**	\brief		Simple function object that expands a test case into a floating 
					 point value. For the TestC45 class this is a simple matter.
	**	\author		Nate Cleveland
	**	\date		2/7/2003 1:52:15 PM
	**	\warning	none
	*/
	////////////////////////////////////////////////////////////////////////////////
	struct TestExpander{float operator()(float val){return val;}};

	//forward declarations.
	class AIUnitAdapter;
	template<class RefObj_type, class Adapter_type, typename Node_type, typename Case_type, typename Class_type, typename Example_type>
		class C45Generator;


	////////////////////////////////////////////////////////////////////////////////
	/*!	\class		C45
	**	\brief		Implements the C45 D-Tree module. Currently only supports AIUnits
	**				 but in the future it will use compile-time polymorphism (ie 
	**				 templitized class) to support ADNs aswell.
	**	\author		Nate Cleveland
	**	\date		11/14/2002 1:47:45 PM
	**	\warning	none
	*/
	////////////////////////////////////////////////////////////////////////////////
	class TestC45
	{

	public:
		//!Short hand typedef for the type of Node used by this class.
		typedef Node<float, bool, TestExpander> TestNode;

		////////////////////////////////////////////////////////////////////////////////
		/*!	\class		TestExample
		**	\brief		Simple example object for this hackish test file.
		**	\author		Nate Cleveland
		**	\date		2/7/2003 1:55:06 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		struct TestExample
		{
			bool				m_result;		//!< result of this example
			std::vector<float>	m_caseVec;		//!< Vector of all the cases at time of example.
		};


		std::vector<TestExample>	m_exampleVec;	//!< vector to store examples in.


		////////////////////////////////////////////////////////////////////////////////
		/*!	\class		AIUnitAdapter
		**	\brief		Adapter object C45Generator object requires us to create.
		**	\author		Nate Cleveland
		**	\date		2/7/2003 1:56:24 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		class AIUnitAdapter
		{
		public:
			//!All typedefs needed to fulfill the C45Generator requirments.
			typedef	TestC45						myRefClass;
			typedef bool						Class_type;
			typedef float						Case_type;
			typedef TestExample					Example_type;
			typedef TestNode					Node_type;

			//!Methods to fulfill the C45Generator requirments.
			static float		GetCaseValue(const Case_type& Case){return Case;}
			static Class_type	GetExampleResult(Example_type ex){return ex.m_result;}
			static Node_type&	GetTreeRootRef(myRefClass& myRef){return *(myRef.m_root);}
			static Node_type*	GetTreeRootPtr(myRefClass& myRef){return myRef.m_root;}
			static Node_type**	GetTreeRootPtrPtr(myRefClass& myRef){return &(myRef.m_root);}
			static Node_type*&	GetTreeRootPtrRef(myRefClass& myRef){return myRef.m_root;}
			static std::vector<Example_type>&	GetExampleVec(myRefClass &myRef){return myRef.m_exampleVec;}
			static const std::vector<Case_type>&GetCaseVec(const Example_type& ex){return ex.m_caseVec;}
		};

		//! Allow the generator object complete access to our data.
		friend AIUnitAdapter;	

		
		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	
		/*!	\brief		Basic Ctor for C45 class.
		**	\return		none
		**	\exception	none
		**	\par		DESCRIPTION:
		**				 Sets members to zero. Nothing else.	
		**	\author		Nate Cleveland
		**	\date		11/14/2002 1:49:12 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		TestC45() throw();


		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	
		/*!	\brief		Defualt dtor for C45 Tree.
		**	\exception	none
		**	\par		DESCRIPTION:
		**				 Frees the tree sturcture and clears out all examples.
		**	\author		Nate Cleveland
		**	\date		11/18/2002 3:12:24 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		~TestC45() throw();


		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	
		/*!	\brief		Creates a deep copy of this object.
		**	\param		toCopyFrom		Reference to the object that we're to copying from.
		**	\exception	none
		**	\par		DESCRIPTION:
		**				 Creates a C45 object that is a copy of the given class. Calls the
		**				  parent's copy ctor.
		**	\author		Nate Cleveland
		**	\date		11/22/2002 3:57:52 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		TestC45(const TestC45& toCopyFrom) throw();
		
		
		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	
		/*!	\brief		saves a tree to file.using c++ streams.
		**	\param		Relative pathname of where to store data.
		**	\return		boolean true false. false == bad.
		**	\exception	none
		**	\author		Nate Cleveland
		**	\date		2/7/2003 1:57:35 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		bool save(const char *pathName = "dTree.acu") throw();
		
		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	
		/*!	\brief		loads a tree from file.
		**	\param		Relative pathname of where to find the data file.
		**	\return		boolean true false. false generally implies unable to find file.
		**	\exception	none
		**	\author		Nate Cleveland
		**	\date		2/7/2003 1:58:29 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		bool load(const char *pathName = "dTree.acu") throw();

		// 
		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	
		/*!	\brief		examines current situation and produces a result.
		**	\param		
		**	\return		none
		**	\exception	none
		**	\par		DESCRIPTION:
		**					
		**	\author		Nate Cleveland
		**	\date		2/7/2003 1:59:16 PM
		**	\warning	case vector size must remain constant during the learning process or 
						 else the tree will crash.
		*/
		////////////////////////////////////////////////////////////////////////////////
		bool Think(std::vector<float> caseVec);

		// 
		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	
		/*!	\brief		uses the c45 generator to reshape the tree structure.
		**	\param		none
		**	\return		none
		**	\exception	none
		**	\par		DESCRIPTION:
		**					If there is an error while generating the tree will set root
							 pointer to null.
		**	\author		Nate Cleveland
		**	\date		2/7/2003 2:00:06 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		void Learn(void) throw();

		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	
		/*!	\brief		Stores the example data given by the caller.
		**	\param		caseVec		vector of current cases.
		**	\param		result		Boolean result of the example.
		**	\return		none
		**	\exception	none
		**	\author		Nate Cleveland
		**	\date		2/7/2003 2:01:32 PM
		**	\warning	asserts case vector size is same as all other cases.
		*/
		////////////////////////////////////////////////////////////////////////////////
		void GiveExample(std::vector<float> caseVec, bool result) throw();

		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	
		/*!	\brief		Clears all examples. Must be done if case vector dimension ever 
						 changes.
		**	\exception	none		
		**	\author		Nate Cleveland
		**	\date		2/7/2003 2:11:26 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		void ClearExampes(void){m_exampleVec.clear();}
		
		
	protected:
		TestNode*						m_root;			//!< Pntr to the tree root.
	};//end TestC45 class.
}//namespace
